﻿using UnityEngine;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using Framework.Utils.SingletonTemplate;
using Debug = UnityEngine.Debug;


namespace Game
{
    public interface IRofBase
    {
        int ReadBody(byte[] rData, int nOffset);
    }

    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
    public class ROFPathAttribute : System.Attribute
    {
        public string TxtName;
        public ROFPathAttribute(string rTxtName)
        {
            this.TxtName = rTxtName;
        }
    }

    public class RofTable<T> where T : IRofBase, new()
    {
        private int mColNum;
        private int mRowNum;

        private Dictionary<int, T> mIDMap;
        private Dictionary<int, int> mRowMap;

        public int RowNum { get { return mRowNum; } }
        public int ColNum { get { return mColNum; } }

        public RofTable(byte[] rTotalBuffer)
        {
            mIDMap = new Dictionary<int, T>();
            mRowMap = new Dictionary<int, int>();

            int nOffset = 64;

            if (BitConverter.IsLittleEndian) { Array.Reverse(rTotalBuffer, nOffset, 4); }
            mRowNum = (int)BitConverter.ToUInt32(rTotalBuffer, nOffset); nOffset += 4;

            if (BitConverter.IsLittleEndian) { Array.Reverse(rTotalBuffer, nOffset, 4); }
            mColNum = (int)BitConverter.ToUInt32(rTotalBuffer, nOffset); nOffset += 4;

            //解析头
            for (int i = 0; i < mColNum; i++)
            {
                int nNameLen = (int)rTotalBuffer[nOffset];
                nOffset += 1 + nNameLen + 2;
            }

            //解析行
            for (int i = 0; i < mRowNum; i++)
            {
                if (BitConverter.IsLittleEndian) { Array.Reverse(rTotalBuffer, nOffset, 4); }
                int nID = (int)BitConverter.ToUInt32(rTotalBuffer, nOffset);
                if (BitConverter.IsLittleEndian) { Array.Reverse(rTotalBuffer, nOffset, 4); }

                T rModel = new T();
                nOffset = rModel.ReadBody(rTotalBuffer, nOffset);
                mIDMap.Add(nID, rModel);
                mRowMap.Add(i, nID);
            }
        }

        public T GetDataByID(int nID)
        {
            if (mIDMap.ContainsKey(nID) == false)
            {
                return default(T);
            }
            return mIDMap[nID];
        }

        public T GetDataByRow(int nIndex)
        {
            if (mRowMap.ContainsKey(nIndex) == false)
            {
                return default(T);
            }
            int nID = mRowMap[nIndex];
            return mIDMap[nID];
        }
    }

    public class RofManager : MgrBase<RofManager>
    {
        //加配置表往下写
        //Example:
        //[ROFPath("RofLanguage")]
        //public RofTable<RofLanguageRow> RofLanguageTable { get; private set; }
        //请按照项目中顺序写
        [ROFPath("RofLanguage")]
        public RofTable<RofLanguageRow> RofLanguageTable { get; private set; }

        //[ROFPath("RofGuide")]
        //public RofTable<RofGuideRow> RofGuideTable { get; private set; }

        private string ConfigPath = "Config/Rof";

        protected override void InitMge()
        {
            Type rType = this.GetType();
            var rBindingFlags = BindingFlags.GetProperty | BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
            var rProInfos = rType.GetProperties(rBindingFlags);
            if (rProInfos == null || rProInfos.Length == 0) return;
            //Debug.LogError(rProInfos.Length);
            var rProInfoEnum = rProInfos.GetEnumerator();
            while (rProInfoEnum.MoveNext())
            {
                var mPinfo    = rProInfoEnum.Current as PropertyInfo;
                var rAttrObjs = mPinfo.GetCustomAttributes(typeof(ROFPathAttribute), false);
                if (rAttrObjs == null || rAttrObjs.Length == 0) continue;
                var rConfigPathAttr = rAttrObjs[0] as ROFPathAttribute;
                if (rConfigPathAttr == null) continue;
                var rRofTxtName = rConfigPathAttr.TxtName;
                var rTxtPath  = string.Format("{0}/{1}", ConfigPath, rRofTxtName);
                var rTxtAsset = Resources.Load<TextAsset>(rTxtPath);
                var rFiledObj = this.Construct(mPinfo.PropertyType, new Type[] {typeof(byte[])}, rTxtAsset.bytes);
                if (rFiledObj != null)
                {
                    mPinfo.SetValue(this, rFiledObj);
                }
                else
                {
                    Debug.LogError(rRofTxtName + "文件有错误");
                }
                Resources.UnloadAsset(rTxtAsset);
            }
        }

        private BindingFlags mFlagsAll = BindingFlags.Instance | BindingFlags.SetField | BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.NonPublic;
        
        private object Construct(Type rType, Type[] rTypes, params object[] rParams)
        {
            var rConstructorInfo = rType.GetConstructor(mFlagsAll, null, rTypes, null);
            return rConstructorInfo.Invoke(rParams);
        }
    }



}
